const express = require('express');
const { exec, spawn } = require('child_process');
const fs = require('fs');
const path = require('path');
const cors = require('cors');
const WebSocket = require('ws');
const http = require('http');

const app = express();
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });

const PORT = 3000;
const TEMP_DIR = path.join(__dirname, 'temp');

// 确保临时目录存在
if (!fs.existsSync(TEMP_DIR)) {
    fs.mkdirSync(TEMP_DIR, { recursive: true });
}

// 中间件
app.use(cors());
app.use(express.json({ limit: '10mb' }));
app.use(express.static(__dirname));

// 存储调试会话
const debugSessions = new Map();

// 编译和运行Java代码
app.post('/api/compile-run', async (req, res) => {
    const { code, className = 'Main' } = req.body;
    
    if (!code) {
        return res.status(400).json({ error: '代码不能为空' });
    }
    
    const sessionId = Date.now().toString();
    const javaFile = path.join(TEMP_DIR, `${className}_${sessionId}.java`);
    const classFile = path.join(TEMP_DIR, `${className}_${sessionId}.class`);
    
    try {
        // 写入Java文件
        fs.writeFileSync(javaFile, code);
        
        // 编译Java代码
        const compileResult = await executeCommand(`javac "${javaFile}"`);
        
        if (compileResult.error) {
            return res.json({
                success: false,
                output: compileResult.stderr || compileResult.error,
                type: 'compile_error'
            });
        }
        
        // 运行Java程序
        const runCommand = `java -cp "${TEMP_DIR}" ${className}_${sessionId}`;
        const runResult = await executeCommand(runCommand, 10000); // 10秒超时
        
        // 清理临时文件
        cleanupFiles([javaFile, classFile]);
        
        res.json({
            success: true,
            output: runResult.stdout || '程序执行完成，无输出',
            stderr: runResult.stderr,
            type: 'success'
        });
        
    } catch (error) {
        // 清理临时文件
        cleanupFiles([javaFile, classFile]);
        
        res.json({
            success: false,
            output: error.message,
            type: 'runtime_error'
        });
    }
});

// 启动调试会话
app.post('/api/debug/start', async (req, res) => {
    const { code, className = 'Main' } = req.body;
    
    if (!code) {
        return res.status(400).json({ error: '代码不能为空' });
    }
    
    const sessionId = Date.now().toString();
    const javaFile = path.join(TEMP_DIR, `${className}_${sessionId}.java`);
    
    try {
        // 写入Java文件
        fs.writeFileSync(javaFile, code);
        
        // 编译Java代码
        const compileResult = await executeCommand(`javac "${javaFile}"`);
        
        if (compileResult.error) {
            return res.json({
                success: false,
                output: compileResult.stderr || compileResult.error,
                type: 'compile_error'
            });
        }
        
        // 创建调试会话
        const debugSession = {
            sessionId,
            className: `${className}_${sessionId}`,
            javaFile,
            code: code.split('\n'),
            currentLine: 0,
            variables: {},
            breakpoints: new Set(),
            isRunning: false
        };
        
        debugSessions.set(sessionId, debugSession);
        
        res.json({
            success: true,
            sessionId,
            message: '调试会话已创建'
        });
        
    } catch (error) {
        cleanupFiles([javaFile]);
        res.json({
            success: false,
            output: error.message,
            type: 'error'
        });
    }
});

// 设置断点
app.post('/api/debug/breakpoint', (req, res) => {
    const { sessionId, line, action } = req.body;
    const session = debugSessions.get(sessionId);
    
    if (!session) {
        return res.status(404).json({ error: '调试会话不存在' });
    }
    
    if (action === 'add') {
        session.breakpoints.add(line);
    } else if (action === 'remove') {
        session.breakpoints.delete(line);
    }
    
    res.json({ success: true, breakpoints: Array.from(session.breakpoints) });
});

// 单步执行
app.post('/api/debug/step', (req, res) => {
    const { sessionId } = req.body;
    const session = debugSessions.get(sessionId);
    
    if (!session) {
        return res.status(404).json({ error: '调试会话不存在' });
    }
    
    try {
        const result = executeDebugStep(session);
        res.json(result);
    } catch (error) {
        res.json({
            success: false,
            error: error.message
        });
    }
});

// 继续执行
app.post('/api/debug/continue', (req, res) => {
    const { sessionId } = req.body;
    const session = debugSessions.get(sessionId);
    
    if (!session) {
        return res.status(404).json({ error: '调试会话不存在' });
    }
    
    try {
        const result = continueExecution(session);
        res.json(result);
    } catch (error) {
        res.json({
            success: false,
            error: error.message
        });
    }
});

// 停止调试
app.post('/api/debug/stop', (req, res) => {
    const { sessionId } = req.body;
    const session = debugSessions.get(sessionId);
    
    if (session) {
        cleanupFiles([session.javaFile, session.javaFile.replace('.java', '.class')]);
        debugSessions.delete(sessionId);
    }
    
    res.json({ success: true, message: '调试会话已停止' });
});

// WebSocket连接处理
wss.on('connection', (ws) => {
    console.log('WebSocket客户端已连接');
    
    ws.on('message', (message) => {
        try {
            const data = JSON.parse(message);
            handleWebSocketMessage(ws, data);
        } catch (error) {
            ws.send(JSON.stringify({ error: '无效的消息格式' }));
        }
    });
    
    ws.on('close', () => {
        console.log('WebSocket客户端已断开连接');
    });
});

// 处理WebSocket消息
function handleWebSocketMessage(ws, data) {
    const { type, sessionId, payload } = data;
    
    switch (type) {
        case 'debug_output':
            // 发送调试输出
            ws.send(JSON.stringify({
                type: 'debug_output',
                data: payload
            }));
            break;
            
        case 'variable_update':
            // 发送变量更新
            ws.send(JSON.stringify({
                type: 'variable_update',
                data: payload
            }));
            break;
    }
}

// 执行命令的辅助函数
function executeCommand(command, timeout = 5000) {
    return new Promise((resolve, reject) => {
        exec(command, { timeout }, (error, stdout, stderr) => {
            if (error) {
                resolve({ error: error.message, stderr, stdout });
            } else {
                resolve({ stdout, stderr });
            }
        });
    });
}

// 执行调试步骤
function executeDebugStep(session) {
    if (session.currentLine >= session.code.length) {
        return {
            success: true,
            finished: true,
            message: '程序执行完成'
        };
    }
    
    const currentLine = session.code[session.currentLine].trim();
    
    // 跳过空行和注释
    if (!currentLine || currentLine.startsWith('//') || currentLine.startsWith('/*')) {
        session.currentLine++;
        return executeDebugStep(session);
    }
    
    // 模拟执行当前行
    const executionResult = simulateLineExecution(currentLine, session);
    session.currentLine++;
    
    return {
        success: true,
        currentLine: session.currentLine - 1,
        variables: session.variables,
        output: executionResult.output,
        finished: false
    };
}

// 继续执行到断点
function continueExecution(session) {
    const outputs = [];
    
    while (session.currentLine < session.code.length) {
        // 检查断点
        if (session.breakpoints.has(session.currentLine)) {
            return {
                success: true,
                currentLine: session.currentLine,
                variables: session.variables,
                output: outputs.join('\n'),
                breakpoint: true,
                message: `在第 ${session.currentLine + 1} 行遇到断点`
            };
        }
        
        const currentLine = session.code[session.currentLine].trim();
        
        if (currentLine && !currentLine.startsWith('//') && !currentLine.startsWith('/*')) {
            const executionResult = simulateLineExecution(currentLine, session);
            if (executionResult.output) {
                outputs.push(executionResult.output);
            }
        }
        
        session.currentLine++;
    }
    
    return {
        success: true,
        finished: true,
        variables: session.variables,
        output: outputs.join('\n'),
        message: '程序执行完成'
    };
}

// 模拟行执行
function simulateLineExecution(line, session) {
    let output = '';
    
    // 处理变量声明和赋值
    const varMatch = line.match(/(?:int|String|double|float|boolean)\s+(\w+)\s*=\s*(.+);?/);
    if (varMatch) {
        const varName = varMatch[1];
        const varValue = varMatch[2].trim();
        
        try {
            if (varValue.startsWith('"') && varValue.endsWith('"')) {
                session.variables[varName] = varValue.slice(1, -1);
            } else if (/^\d+$/.test(varValue)) {
                session.variables[varName] = parseInt(varValue);
            } else {
                // 简单的表达式计算
                session.variables[varName] = evaluateExpression(varValue, session.variables);
            }
        } catch (error) {
            session.variables[varName] = varValue;
        }
    }
    
    // 处理输出语句
    const printMatch = line.match(/System\.out\.println?\s*\(\s*(.+)\s*\);?/);
    if (printMatch) {
        let printValue = printMatch[1].trim();
        
        if (printValue.startsWith('"') && printValue.endsWith('"')) {
            output = printValue.slice(1, -1);
        } else {
            // 替换变量并计算表达式
            output = evaluateExpression(printValue, session.variables).toString();
        }
    }
    
    return { output };
}

// 计算表达式
function evaluateExpression(expr, variables) {
    let result = expr;
    
    // 替换变量
    for (const [varName, value] of Object.entries(variables)) {
        const regex = new RegExp('\\b' + varName + '\\b', 'g');
        result = result.replace(regex, value.toString());
    }
    
    // 处理字符串连接
    if (result.includes('+') && result.includes('"')) {
        const parts = result.split('+').map(part => part.trim());
        let finalResult = '';
        
        for (const part of parts) {
            if (part.startsWith('"') && part.endsWith('"')) {
                finalResult += part.slice(1, -1);
            } else {
                finalResult += part;
            }
        }
        
        return finalResult;
    }
    
    // 简单的数学计算
    try {
        return Function('"use strict"; return (' + result + ')')();
    } catch (error) {
        return result;
    }
}

// 清理临时文件
function cleanupFiles(files) {
    files.forEach(file => {
        if (fs.existsSync(file)) {
            try {
                fs.unlinkSync(file);
            } catch (error) {
                console.error(`清理文件失败: ${file}`, error);
            }
        }
    });
}

// 定期清理过期的调试会话
setInterval(() => {
    const now = Date.now();
    for (const [sessionId, session] of debugSessions.entries()) {
        if (now - parseInt(sessionId) > 30 * 60 * 1000) { // 30分钟过期
            cleanupFiles([session.javaFile, session.javaFile.replace('.java', '.class')]);
            debugSessions.delete(sessionId);
        }
    }
}, 5 * 60 * 1000); // 每5分钟检查一次

// 启动服务器
server.listen(PORT, () => {
    console.log(`Java编辑器服务器运行在 http://localhost:${PORT}`);
    console.log('功能特性:');
    console.log('- 代码编辑和语法高亮');
    console.log('- Java代码编译和运行');
    console.log('- 调试功能（断点、单步执行、变量查看）');
    console.log('- 实时WebSocket通信');
});